package mq

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/streadway/amqp"
	"gugojudger/env"
	"gugojudger/judger"
	"time"
)

var CommitChan chan *judger.Question
var JudgeChan chan *judger.OJResult
var initd bool

// StartMQProduce 消息队列生产者
func StartMQProduce(ctx context.Context, channel *amqp.Channel) {
	if initd {
		return
	}
	initd = true
	go judger.JudgerByMQ(CommitChan, JudgeChan)
	select {
	case <-ctx.Done():
		return
	case ojrsult := <-JudgeChan:
		jsonstr, _ := json.Marshal(ojrsult)
		err := channel.Publish("JudgeDirectExchange",
			"JudgedDirectQueueKey",
			true,
			false,
			amqp.Publishing{
				Timestamp:    time.Now(),
				DeliveryMode: amqp.Persistent,
				ContentType:  "text/plain",
				Body:         jsonstr,
			})
		if err != nil {
			fmt.Println("Send message failed; ", err)
		}

	}
}

// StartMQConsume 消息队列消费者
func StartMQConsume(ctx context.Context) {
	//提交队列（已完成）
	CommitChan = make(chan *judger.Question)
	//判题队列（准备中）
	JudgeChan = make(chan *judger.OJResult)
	//获取mq地址
	mqAddr, err := env.GetConfig("rabbitmqUrl")
	if err != nil {
		fmt.Println(err.Error())
		return
	}

	conn, err := amqp.Dial(mqAddr)
	if err != nil {
		fmt.Println("RabbitMQ connect failed: ", err)
	}
	defer conn.Close()

	ch, err := conn.Channel()
	if err != nil {
		fmt.Println("Got channel failed: ", err)
	}

	queue, err := ch.QueueDeclare(
		"CommitDirectQueue",
		true,
		false,
		false,
		false,
		nil,
	)
	if err != nil {
		fmt.Println("Queue declared failed: ", err)
	}

	msgs, err := ch.Consume(
		queue.Name,   //队列名称
		"gugojudger", //消费者
		true,         //自动确认
		false,        //排他
		false,
		false,
		nil,
	)
	if err != nil {
		fmt.Println("Got Consumer failed: ", err)
	}

	err = ch.ExchangeDeclare(
		"JudgeDirectExchange",
		"direct",
		true,
		false,
		false,
		true,
		nil,
	)
	if err != nil {
		fmt.Println("Create exchange failed: ", err.Error())
	}
	_, err = ch.QueueDeclare(
		"JudgedDirectQueue",
		true,
		false,
		false,
		false,
		nil,
	)
	if err != nil {
		fmt.Println("Queue declared failed: ", err)
	}

	err = ch.QueueBind("JudgedDirectQueue",
		"JudgedDirectQueueKey",
		"JudgeDirectExchange",
		true,
		nil)
	if err != nil {
		fmt.Println("Queue bind failed: ", err)
	}

	//开始启动队列生产者
	ctxProduce, produceCancel := context.WithCancel(ctx)
	defer produceCancel()
	go StartMQProduce(ctxProduce, ch)

	for {

		select {
		case <-ctx.Done():
			return

		case message := <-msgs:
			question := judger.Question{}
			err = json.Unmarshal(message.Body, &question)
			if err != nil {
				fmt.Println(err.Error())
			}

			CommitChan <- &question
		}
	}
}
